package org.zjt.platform.druid.spring.boot.starter;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author juntao.zhang
 * @version V1.0
 * @Description: 配置druid的dashboard
 * @Package org.zjt.platform.driuddemo.config
 * @date 2018/3/12 21:20
 */
@Configuration
@EnableConfigurationProperties({DruidProperties.class})
@ConditionalOnClass(name = "com.alibaba.druid.pool.DruidDataSource")
@ConditionalOnBean({DataSource.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
@ConditionalOnProperty(prefix = "spring.datasource.monitor",name = "enable",havingValue = "true",matchIfMissing = true)
public class DruidAutoConfiguration {

    /**
     * 慢查询sql展示
     * @param dataSource
     * @return
     */
    @Bean
    public StatFilter statFilter(DataSource dataSource,DruidProperties druidProperties) {
        if (!(dataSource instanceof DruidDataSource) || Objects.isNull(druidProperties.getSlowSqlMillis()))
            return null;
        StatFilter statFilter = new StatFilter();
        statFilter.setMergeSql(true);
        statFilter.setSlowSqlMillis(druidProperties.getSlowSqlMillis());
        statFilter.setLogSlowSql(true);
        DruidDataSource.class.cast(dataSource).setProxyFilters(Arrays.asList(statFilter));
        return statFilter;
    }


    @Configuration
    @ConditionalOnProperty(prefix = "spring.datasource.monitor",name = "spring-monitor-enable",havingValue = "true",matchIfMissing = false)
    public class DruidSpringMonitorAutoConfiguration{
       /**
        * spring 监控配置，监控方法执行
        * @return
        */
       @Bean
       public DruidStatInterceptor druidStatInterceptor() {
           DruidStatInterceptor druidStatInterceptor = new DruidStatInterceptor();
           return druidStatInterceptor;
       }


       @Bean
       public JdkRegexpMethodPointcut jdkRegexpMethodPointcut(DruidProperties druidProperties) {
           List<String> patterns ;
           if (Objects.isNull(druidProperties) || Objects.isNull(druidProperties.getPatterns()))
               patterns = Collections.emptyList();
            else
                patterns= druidProperties.getPatterns().stream().map(item ->item.replace("\\","")).collect(Collectors.toList());
           JdkRegexpMethodPointcut jdkRegexpMethodPointcut = new JdkRegexpMethodPointcut();
           Assert.notEmpty(patterns,"spring.datasource.monitor.patterns");
           String[] strings = patterns.toArray(new String[patterns.size()]);
           jdkRegexpMethodPointcut.setPatterns(strings);
           return jdkRegexpMethodPointcut;
       }

       @Bean
       @ConditionalOnBean({DruidStatInterceptor.class,JdkRegexpMethodPointcut.class})
       public DefaultBeanFactoryPointcutAdvisor aspectJPointcutAdvisor(JdkRegexpMethodPointcut jdkRegexpMethodPointcut,DruidStatInterceptor druidStatInterceptor) {
           DefaultBeanFactoryPointcutAdvisor defaultBeanFactoryPointcutAdvisor = new DefaultBeanFactoryPointcutAdvisor();
           defaultBeanFactoryPointcutAdvisor.setPointcut(jdkRegexpMethodPointcut);
           defaultBeanFactoryPointcutAdvisor.setAdvice(druidStatInterceptor);
           return defaultBeanFactoryPointcutAdvisor;
       }
   }

}